package com.egao.common.manage.big.controller;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.egao.common.core.web.BaseController;
import com.egao.common.core.web.JsonResult;
import com.egao.common.manage.big.vo.*;
import com.egao.common.module.company.constants.CompanyConstants;
import com.egao.common.module.company.entity.*;
import com.egao.common.module.company.service.*;
import com.egao.common.module.counsel.entity.Counsel;
import com.egao.common.module.counsel.entity.CounselStudent;
import com.egao.common.module.counsel.enums.CounselTypeEnum;
import com.egao.common.module.counsel.service.CounselStudentService;
import com.egao.common.module.pepesi.service.PepsiStudentService;
import com.egao.common.module.pushInformation.PushInformationConstants;
import com.egao.common.module.pushInformation.entity.PushInformation;
import com.egao.common.module.pushInformation.service.PushInformationService;
import com.egao.common.module.student.constants.StudentConstants;
import com.egao.common.module.student.constants.StudentSignConstants;
import com.egao.common.module.student.entity.Student;
import com.egao.common.module.student.entity.StudentSign;
import com.egao.common.module.student.service.StudentService;
import com.egao.common.module.student.service.StudentSignService;
import com.egao.common.module.system.constants.DictConstants;
import com.egao.common.module.system.entity.College;
import com.egao.common.module.system.entity.Dict;
import com.egao.common.module.system.service.CollegeService;
import com.egao.common.module.system.service.DictService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

@Api(tags = "大屏数据源")
@RestController
@RequestMapping("${api}")
public class BigDataController extends BaseController {

    @Resource
    private PreachService preachService;
    @Resource
    private MutualService mutualService;
    @Resource
    private PreachCloudService preachCloudService;
    @Resource
    private StudentService studentService;
    @Resource
    private StudentSignService studentSignService;
    @Resource
    private CollegeService collegeService;
    @Resource
    private DictService dictService;
    @Resource
    private PushInformationService pushInformationService;
    @Resource
    private CompanyService companyService;
    @Resource
    private PositionService positionService;
    @Resource
    private CounselStudentService counselStudentService;
    @Resource
    private PepsiStudentService pepsiStudentService;

    /**
     * 全国省份
     */
    private final String[] AREA = new String[]{"北京", "天津", "河北", "山西", "内蒙古", "辽宁", "吉林", "黑龙江", "上海", "江苏", "浙江", "安徽", "福建", "江西", "山东", "河南", "湖北", "湖南", "广东", "广西", "海南", "重庆", "四川", "贵州", "云南", "西藏", "陕西", "甘肃", "青海", "宁夏", "新疆", "台湾", "香港", "澳门"};


    @PreAuthorize("hasAuthority('big:data')")
    @ApiOperation(value = "年度招聘开展情况")
    @GetMapping("/big/data/zpkz")
    public JsonResult zpkz(Integer year) throws Exception {
        BigDataZpkzVO vo = new BigDataZpkzVO();
        String[] dateRange = dateRange(year);

        Date today = new Date();
        Date todayStart = DateUtil.beginOfDay(today);
        Date todayEnd = DateUtil.endOfDay(today);

        // 校内宣讲会 start
        // 查询举办时间在日期范围内有效的校内宣讲会
        List<Preach> preachList = preachService.list(new LambdaQueryWrapper<Preach>()
                .select(Preach::getId, Preach::getHoldTime)
                .eq(Preach::getInvalid, 0)
                .eq(Preach::getState, "1")
                .between(Preach::getHoldTime, dateRange[0], dateRange[1])
        );

        // 今日宣讲会场次
        int preachTodayCount = (int) preachList.stream().filter(preach -> preach.getHoldTime().getTime() >= todayStart.getTime() && preach.getHoldTime().getTime() <= todayEnd.getTime()).count();

        // 宣讲会赋值
        vo.setPreachCount(preachList.size());
        vo.setPreachTodayCount(preachTodayCount);
        vo.setPreachStudentCount(0);

        // 校内双选会 start
        // 查询举办时间在日期范围内有效的校内双选会
        List<Mutual> mutualList = mutualService.list(new LambdaQueryWrapper<Mutual>()
                .select(Mutual::getId, Mutual::getStartTime)
                .eq(Mutual::getInvalid, 0)
                .between(Mutual::getStartTime, dateRange[0], dateRange[1])
        );

        // 今日双选会场次
        int mutualTodayCount = (int) mutualList.stream().filter(mutual -> mutual.getStartTime().getTime() >= todayStart.getTime() && mutual.getStartTime().getTime() <= todayEnd.getTime()).count();

        // 双选会赋值
        vo.setMutualCount(mutualList.size());
        vo.setMutualTodayCount(mutualTodayCount);
        vo.setMutualStudentCount(0);

        // 空中宣讲会 start
        // 查询举办时间在日期范围内有效的校内空中宣讲会
        List<PreachCloud> preachCloudList = preachCloudService.list(new LambdaQueryWrapper<PreachCloud>()
                .select(PreachCloud::getId, PreachCloud::getHoldTime)
                .eq(PreachCloud::getInvalid, 0)
                .eq(PreachCloud::getState, "1")
                .between(PreachCloud::getHoldTime, dateRange[0], dateRange[1])
        );

        // 今日空中宣讲会场次
        int preachCloudTodayCount = (int) preachCloudList.stream().filter(preachCloud -> preachCloud.getHoldTime().getTime() >= todayStart.getTime() && preachCloud.getHoldTime().getTime() <= todayEnd.getTime()).count();

        // 空中宣讲会赋值
        vo.setPreachCloudCount(preachCloudList.size());
        vo.setPreachCloudTodayCount(preachCloudTodayCount);
        vo.setPreachCloudStudentCount(0);

        return JsonResult.ok().setData(vo);
    }

    @PreAuthorize("hasAuthority('big:data')")
    @ApiOperation(value = "就业意愿情况")
    @GetMapping("/big/data/jyyy")
    public JsonResult jyyy(Integer year) {
        BigDataJyyyVO vo = new BigDataJyyyVO();

        // 本科年份
        int[] bkYears = new int[]{year, year - 1, year - 2, year - 3};
        // 研究生年份
        int[] yjsYears = new int[]{year, year - 1, year - 2};

        // 4年学生数据
        List<Student> studentList = studentService.list(new LambdaQueryWrapper<Student>()
                .select(Student::getId, Student::getYearId, Student::getXl, Student::getDegree,
                        Student::getKnslb, Student::getMz,
                        Student::getInten, Student::getIntenName, Student::getIntenAddress, Student::getIntenIndustry, Student::getIntenSalary, Student::getSalary)
                .in(Student::getYearId, Arrays.stream(bkYears).boxed().collect(Collectors.toList()))
        );

        // 当前毕业年份学生数据
        List<Student> currentStudentList = studentList.stream().filter(d -> year.equals(d.getYearId())).collect(Collectors.toList());

        // TODO 正式环境数据需要格式化 去掉空格和[]
        // 意愿匹配
        String inten = currentStudentList.stream().map(Student::getInten).filter(d -> !StrUtil.isBlank(d)).collect(Collectors.joining(","));
        List<BigDataVO> intenList = buildBigDataVO(inten);
        vo.setIntentionList(intenList);

        // 薪资分布
        String salary = currentStudentList.stream().map(Student::getSalary).filter(d -> !StrUtil.isBlank(d)).collect(Collectors.joining(","));
        List<BigDataVO> salaryList = buildBigDataVO(salary);
        vo.setSalaryList(salaryList.subList(0, Math.min(salaryList.size(), 4)));

        // 地域前三
        String intenAddress = currentStudentList.stream().map(Student::getIntenAddress).filter(d -> !StrUtil.isBlank(d)).collect(Collectors.joining(","));
        List<BigDataVO> intenAddressList = buildBigDataVO(intenAddress);
        vo.setAreaList(intenAddressList.subList(0, Math.min(intenAddressList.size(), 3)));

        // 岗位前三
        String intenName = currentStudentList.stream().map(Student::getIntenName).filter(d -> !StrUtil.isBlank(d)).collect(Collectors.joining(","));
        List<BigDataVO> intenNameList = buildBigDataVO(intenName);
        vo.setPositionList(intenNameList.subList(0, Math.min(intenNameList.size(), 3)));

        // 行业前三
        String intenIndustry = currentStudentList.stream().map(Student::getIntenIndustry).filter(d -> !StrUtil.isBlank(d)).collect(Collectors.joining(","));
        List<BigDataVO> industryList = buildBigDataVO(intenIndustry);
        vo.setIndustryList(industryList.subList(0, Math.min(industryList.size(), 3)));

        // 所有就业意向分类
        String intention = studentList.stream().map(Student::getInten).filter(d -> !StrUtil.isBlank(d)).distinct().collect(Collectors.joining(","));
        List<String> intentionList = Arrays.stream(intention.split(",")).distinct().collect(Collectors.toList());

        // 当前毕业年份困难生(非困难生类别)
        List<Student> knsStudentList = currentStudentList.stream().filter(d -> !StrUtil.isBlank(d.getKnslb()) && !"0".equals(d.getKnslb())).collect(Collectors.toList());
        // 当前毕业年份民族生(非汉族学生)
        List<Student> mzStudentList = currentStudentList.stream().filter(d -> !StrUtil.isBlank(d.getMz()) && !"01".equals(d.getMz())).collect(Collectors.toList());
        List<Integer> knsStudentData = new ArrayList<>();
        List<Integer> mzStudentData = new ArrayList<>();
        for (String intentionItem : intentionList) {
            int knsStudentCount = (int) knsStudentList.stream().filter(d -> !StrUtil.isBlank(d.getInten()) && d.getInten().contains(intentionItem)).count();
            knsStudentData.add(knsStudentCount);
            int mzStudentCount = (int) mzStudentList.stream().filter(d -> !StrUtil.isBlank(d.getInten()) && d.getInten().contains(intentionItem)).count();
            mzStudentData.add(mzStudentCount);
        }
        vo.setIntentionKnsData(knsStudentData.stream().mapToInt(Integer::intValue).toArray());
        vo.setIntentionMzData(mzStudentData.stream().mapToInt(Integer::intValue).toArray());

        // 就业意向分毕业年份和学历数据源
        // 维度 ["求职", "考公", "考研", "升学"]
        // X轴 [2024, 2023, 2022, 2021]
        // Y轴 [[2024求职, 2023求职, 2022求职], [2024考公, 2023考公, 2022考公]]
        // 就业意向本科数据源
        List<int[]> intentionBkDataGroup = new ArrayList<>();
        // 就业意向研究生数据源
        List<int[]> intentionYjsDataGroup = new ArrayList<>();
        for (String intentionItem : intentionList) {
            List<Integer> intentionBkData = new ArrayList<>();
            List<Integer> intentionYjsData = new ArrayList<>();
            for (Integer yearItem : bkYears) {
                List<Student> list = studentList.stream().filter(d -> yearItem.equals(d.getYearId())
                        && !StrUtil.isBlank(d.getInten()) && d.getInten().contains(intentionItem)
                ).collect(Collectors.toList());

                int bkCount = (int) list.stream().filter(d -> StudentConstants.STUDENT_DEGREE_BK.equals(d.getDegree())).count();
                intentionBkData.add(bkCount);

                int yjsCount = (int) list.stream().filter(d -> StudentConstants.STUDENT_DEGREE_YJS.equals(d.getDegree())).count();
                intentionYjsData.add(yjsCount);
            }

            intentionBkDataGroup.add(intentionBkData.stream().mapToInt(Integer::intValue).toArray());
            intentionYjsDataGroup.add(intentionYjsData.stream().mapToInt(Integer::intValue).toArray());
        }

        // 就业意向完成状态分毕业年份和学历
        List<Integer> intentionDoneBkData = new ArrayList<>();
        List<Double> intentionDoneBkDataRate = new ArrayList<>();
        List<Integer> intentionDoneYjsData = new ArrayList<>();
        List<Double> intentionDoneYjsDataRate = new ArrayList<>();
        for (Integer yearItem : bkYears) {
            // 本科生源
            List<Student> bkStudentList = studentList.stream().filter(d -> yearItem.equals(d.getYearId()) && StudentConstants.STUDENT_DEGREE_BK.equals(d.getDegree())).collect(Collectors.toList());
            // 本科完成就业意向人数
            int bkStudentCount = (int) bkStudentList.stream().filter(d -> !StrUtil.isBlank(d.getInten())).count();
            // 本科完成就业意向占比
            double bkStudentRate = NumberUtil.mul(NumberUtil.div(bkStudentCount, bkStudentList.size(), 2, RoundingMode.HALF_UP), 100);
            intentionDoneBkData.add(bkStudentCount);
            intentionDoneBkDataRate.add(bkStudentRate);

            // 研究生生源
            List<Student> yjsStudentList = studentList.stream().filter(d -> yearItem.equals(d.getYearId()) && StudentConstants.STUDENT_DEGREE_YJS.equals(d.getDegree())).collect(Collectors.toList());
            // 研究生完成就业意向人数
            int yjsStudentCount = (int) yjsStudentList.stream().filter(d -> !StrUtil.isBlank(d.getInten())).count();
            // 研究生完成就业意向占比
            double yjsStudentRate = NumberUtil.mul(NumberUtil.div(yjsStudentCount, yjsStudentList.size(), 2, RoundingMode.HALF_UP), 100);
            intentionDoneYjsData.add(yjsStudentCount);
            intentionDoneYjsDataRate.add(yjsStudentRate);
        }

        // 创建就业意向类别数组 其中升学(出国出境)翻译成升学显示
        String[] intentions = new String[intentionList.size()];
        for (int i = 0; i < intentionList.size(); i++) {
            String name = intentionList.get(i);
            if (name.contains("升学")) {
                name = "升学";
            }
            intentions[i] = name;
        }

        vo.setIntentions(intentions);
        vo.setYears(bkYears);
        vo.setIntentionBkData(intentionBkDataGroup);
        vo.setIntentionYjsData(intentionYjsDataGroup);
        vo.setIntentionDoneBkData(intentionDoneBkData.stream().mapToInt(Integer::intValue).toArray());
        vo.setIntentionDoneBkDataRate(intentionDoneBkDataRate.stream().mapToDouble(Double::doubleValue).toArray());
        vo.setIntentionDoneYjsData(intentionDoneYjsData.stream().mapToInt(Integer::intValue).toArray());
        vo.setIntentionDoneYjsDataRate(intentionDoneYjsDataRate.stream().mapToDouble(Double::doubleValue).toArray());

        return JsonResult.ok().setData(vo);
    }

    @PreAuthorize("hasAuthority('big:data')")
    @ApiOperation(value = "生源签约")
    @GetMapping("/big/data/syqy")
    public JsonResult syqy(Integer year, Integer degree) {
        BigDataSyqyVO vo = new BigDataSyqyVO();

        // 查询一年的学生生源数据
        List<Student> studentList = studentService.list(new LambdaQueryWrapper<Student>()
                .select(Student::getId, Student::getCollegeCode, Student::getXb, Student::getXl, Student::getSyszd, Student::getPyfs)
                .eq(Student::getYearId, year)
        );
        if (CollectionUtil.isEmpty(studentList)) {
            return JsonResult.ok().setData(vo);
        }

        // 总生源人数
        int studentCount = studentList.size();
        vo.setStudentCount(studentCount);

        // 本科生人数和占比
        int studentBkCount = (int) studentList.stream().filter(student -> StudentConstants.STUDENT_XL_BK.equals(student.getXl()) || StudentConstants.STUDENT_XL_BKRXW.equals(student.getXl())).count();
        String studentBkRate = NumberUtil.formatPercent(NumberUtil.div(studentBkCount, studentCount), 2);
        vo.setStudentBkCount(studentBkCount);
        vo.setStudentBkRate(studentBkRate);

        // 硕士生人数
        int studentSsCount = (int) studentList.stream().filter(student -> StudentConstants.STUDENT_XL_SS.equals(student.getXl())).count();
        String studentSsRate = NumberUtil.formatPercent(NumberUtil.div(studentSsCount, studentCount), 2);
        vo.setStudentSsCount(studentSsCount);
        vo.setStudentSsRate(studentSsRate);

        // 博士生人数
        int studentBsCount = (int) studentList.stream().filter(student -> StudentConstants.STUDENT_XL_BS.equals(student.getXl())).count();
        String studentBsRate = NumberUtil.formatPercent(NumberUtil.div(studentBsCount, studentCount), 2);
        vo.setStudentBsCount(studentBsCount);
        vo.setStudentBsRate(studentBsRate);

        // 当前所有生源的有效毕业去向
        List<StudentSign> studentSignList = studentSignService.listBigData(year);

        // 学院数据
        List<College> collegeList = collegeService.listAll(degree, "");
        // 生源地数据
        List<Dict> syszdList = dictService.cacheList(DictConstants.TYPE_SYSZD);

        // 构建学生的毕业去向
        for (Student student : studentList) {
            // 翻译学院
            College college = collegeList.stream().filter(d -> d.getCode().equals(student.getCollegeCode())).findFirst().orElse(null);
            student.setCollegeName(college != null ? college.getName() : "");

            // 翻译生源省
            Dict syszdDict = syszdList.stream().filter(d -> d.getValue().equals(student.getSyszd())).findFirst().orElse(null);
            student.setSysf(buildArea(syszdDict != null ? syszdDict.getLabel() : ""));

            // 记录毕业去向 start
            // 学生是定向生计入到协议就业中
            if (StudentConstants.PYFS_DX.equals(student.getPyfs())) {
                student.setSignCategory(StudentSignConstants.SIGN_CATEGORY_XYJY);
                continue;
            }
            // 绑定学生毕业去向 没有绑定待就业
            StudentSign studentSign = studentSignList.stream().filter(d -> student.getId().equals(d.getStudentId())).findFirst().orElse(null);
            if (studentSign != null) {
                student.setSignCategory(studentSign.getSignCategory());
            } else {
                student.setSignCategory(StudentSignConstants.SIGN_CATEGORY_DJY);
            }
        }

        // 就业率(排除毕业去向待就业)
        List<Student> studentWorkList = studentList.stream().filter(d -> !StudentSignConstants.SIGN_CATEGORY_DJY.equals(d.getSignCategory())).collect(Collectors.toList());

        // 本科就业人数及占比
        int studentSignBkCount = (int) studentWorkList.stream().filter(d -> StudentConstants.STUDENT_XL_BK.equals(d.getXl()) || StudentConstants.STUDENT_XL_BKRXW.equals(d.getXl())).count();
        String studentSignBkRate = NumberUtil.formatPercent(NumberUtil.div(studentSignBkCount, studentBkCount), 2);
        vo.setStudentSignBkCount(studentSignBkCount);
        vo.setStudentSignBkRate(studentSignBkRate);

        // 硕士就业人数及占比
        int studentSignSsCount = (int) studentWorkList.stream().filter(d -> StudentConstants.STUDENT_XL_SS.equals(d.getXl())).count();
        String studentSignSsRate = NumberUtil.formatPercent(NumberUtil.div(studentSignSsCount, studentSsCount), 2);
        vo.setStudentSignSsCount(studentSignSsCount);
        vo.setStudentSignSsRate(studentSignSsRate);

        // 博士就业人数及占比
        int studentSignBsCount = (int) studentWorkList.stream().filter(d -> StudentConstants.STUDENT_XL_BS.equals(d.getXl())).count();
        String studentSignBsRate = NumberUtil.formatPercent(NumberUtil.div(studentSignBsCount, studentBsCount), 2);
        vo.setStudentSignBsCount(studentSignBsCount);
        vo.setStudentSignBsRate(studentSignBsRate);

        // 根据生源省份记录生源和就业率
        List<BigDataSyqyAreaVO> areaVOList = new ArrayList<>();
        for (String area : AREA) {
            // 生源人数
            int areaStudentCount = 0;
            // 就业人数
            int areaStudentSignCount = 0;

            for (Student student : studentList) {
                if (!area.equals(student.getSysf())) {
                    continue;
                }
                areaStudentCount++;
                if (!StudentSignConstants.SIGN_CATEGORY_DJY.equals(student.getSignCategory())) {
                    areaStudentSignCount++;
                }
            }

            BigDataSyqyAreaVO areaVO = new BigDataSyqyAreaVO();
            areaVO.setText(area);
            areaVO.setStudentCount(areaStudentCount);
            areaVO.setStudentRate(NumberUtil.formatPercent(NumberUtil.div(areaStudentCount, studentCount), 2));
            areaVO.setStudentSignCount(areaStudentSignCount);
            areaVO.setStudentSignRate(NumberUtil.formatPercent(NumberUtil.div(areaStudentSignCount, studentCount), 2));
            areaVOList.add(areaVO);
        }
        vo.setAreaList(areaVOList);

        // 学院就业率和学院中学历毕业去向人数
        List<BigDataSyqyCollegeVO> collegeVOList = new ArrayList<>();
        for (College college : collegeList) {
            BigDataSyqyCollegeVO collegeVO = new BigDataSyqyCollegeVO();
            
            // 学院学生人数
            int collegeStudentCount = 0;

            // 学院下各学历各就业方式毕业去向人数
            for (Student student : studentList) {
                if (!college.getName().equals(student.getCollegeName())) {
                    continue;
                }
                collegeStudentCount++;

                switch (student.getSignCategory()) {
                    case StudentSignConstants.SIGN_CATEGORY_XYJY:
                        collegeVO.setXyjy(collegeVO.getXyjy() + 1);
                        break;
                    case StudentSignConstants.SIGN_CATEGORY_ZZCY:
                        collegeVO.setZzcy(collegeVO.getZzcy() + 1);
                        break;
                    case StudentSignConstants.SIGN_CATEGORY_ZYZY:
                        collegeVO.setZyzy(collegeVO.getZyzy() + 1);
                        break;
                    case StudentSignConstants.SIGN_CATEGORY_SX:
                        collegeVO.setSx(collegeVO.getSx() + 1);
                        break;
                    case StudentSignConstants.SIGN_CATEGORY_CGCJ:
                        collegeVO.setCgcj(collegeVO.getCgcj() + 1);
                        break;
                    case StudentSignConstants.SIGN_CATEGORY_DJY:
                        collegeVO.setDjy(collegeVO.getDjy() + 1);
                        break;
                }
            }
            // 学院没有人不在继续
            if (collegeStudentCount == 0) {
                continue;
            }

            // 学院学生就业率人数
            int collegeStudentSignCount = (int) studentWorkList.stream().filter(d -> college.getName().equals(d.getCollegeName())).count();
            // 学院学生就业率
            double collegeStudentSignRateDouble = NumberUtil.div(collegeStudentSignCount, collegeStudentCount);
            String collegeStudentSignRate = NumberUtil.formatPercent(collegeStudentSignRateDouble, 2);

            collegeVO.setText(college.getName());
            collegeVO.setStudentCount(collegeStudentCount);
            collegeVO.setStudentSignCount(collegeStudentSignCount);
            collegeVO.setStudentSignRateDouble(collegeStudentSignRateDouble);
            collegeVO.setStudentSignRate(collegeStudentSignRate);
            collegeVOList.add(collegeVO);
        }
        // 学院就业率取前五
//        collegeVOList.sort(Comparator.comparingInt(BigDataSyqyCollegeVO::getStudentSignRateDouble).reversed());
//        vo.setCollegeList(collegeVOList.subList(0, Math.min(collegeVOList.size(), 5)));
        vo.setCollegeList(collegeVOList);

        // 学院数组
        // 学院就业率数组
        // 就业方式数组
        // 某个学院的就业方式就业率数组

        vo.setSignCategory(new String[]{"协议", "创业", "自由", "升学", "出国出境", "待就业"});
        return JsonResult.ok().setData(vo);
    }

    @PreAuthorize("hasAuthority('big:data')")
    @ApiOperation(value = "精准匹配")
    @GetMapping("/big/data/jzpp")
    public JsonResult jzpp(Integer year) {
        BigDataJzppVO vo = new BigDataJzppVO();

        // 2020年旧版数据处理
        if (2020 == year) {
            vo.setCount(53901);
            vo.setReadCount(4730);
            vo.setResumeCount(26);
            vo.setCollegeNames(new String[]{"会计学院", "法学院", "工商管理学院"});
            vo.setCollegeCounts(new int[]{7618, 6949, 4727});
            vo.setCollegeReadCounts(new int[]{431, 735, 362});
            return JsonResult.ok().setData(vo);
        }

        // 2021年旧版数据处理
        if (2021 == year) {
            vo.setCount(5791715);
            vo.setReadCount(117125);
            vo.setResumeCount(2635);
            vo.setCollegeNames(new String[]{"法学院", "会计学院", "工商管理学院"});
            vo.setCollegeCounts(new int[]{784066, 523858, 458380});
            vo.setCollegeReadCounts(new int[]{16046, 6273, 7629});
            return JsonResult.ok().setData(vo);
        }

        // 2022年旧版数据处理
        if (2022 == year) {
            vo.setCount(7239347);
            vo.setReadCount(153085);
            vo.setResumeCount(11974);
            vo.setCollegeNames(new String[]{"法学院", "会计学院", "工商管理学院"});
            vo.setCollegeCounts(new int[]{793635, 585031, 571850});
            vo.setCollegeReadCounts(new int[]{13546, 10722, 15404});
            return JsonResult.ok().setData(vo);
        }

        // 2023年旧版数据处理
        if (2023 == year) {
            vo.setCount(851168);
            vo.setReadCount(67393);
            vo.setResumeCount(1860);
            vo.setCollegeNames(new String[]{"会计学院研", "金融学院研", "工商管理学院研"});
            vo.setCollegeCounts(new int[]{97080, 92260, 80930});
            vo.setCollegeReadCounts(new int[]{8288, 7316, 5695});
            return JsonResult.ok().setData(vo);
        }

        // 查询所有已推送信息
        List<PushInformation> pushInformationList = pushInformationService.list(new LambdaQueryWrapper<PushInformation>()
                .eq(PushInformation::getPushState, PushInformationConstants.PUSH_STATE_SUCCESS)
                .eq(PushInformation::getYearId, year)
        );
        // 过滤一遍没有学院的数据
        pushInformationList = pushInformationList.stream().filter(d -> !StrUtil.isBlank(d.getCollegeName())).collect(Collectors.toList());
        vo.setCount(pushInformationList.size());

        // 查看个数
        int readCount = (int) pushInformationList.stream().filter(d -> PushInformationConstants.READ_STATE_READ == d.getReadState()).count();
        vo.setReadCount(readCount);

        // 发送简历个数
        int resumeCount = (int) pushInformationList.stream().filter(d -> PushInformationConstants.RESUME_STATE_SEND == d.getResumeState()).count();
        vo.setResumeCount(resumeCount);

        // 学院分组统计 倒叙排序
        Map<String, Long> collegeGroupMap = pushInformationList.stream().collect(Collectors.groupingBy(PushInformation::getCollegeName, Collectors.counting()));
        List<Map.Entry<String, Long>> collegeGroupList = new ArrayList<Map.Entry<String, Long>>(collegeGroupMap.entrySet());
        collegeGroupList.sort(new Comparator<Map.Entry<String, Long>>() {
            public int compare(Map.Entry<String, Long> o1, Map.Entry<String, Long> o2) {
                return (int) (o2.getValue() - o1.getValue());
            }
        });
        // 学院取前三个结果
        List<String> collegeList = new ArrayList<>();
        List<Integer> countList = new ArrayList<>();
        List<Integer> readCountList = new ArrayList<>();
        for (int i = 0; i < collegeGroupList.size(); i++) {
            if (i == 3) {
                break;
            }

            String itemCollegeName = collegeGroupList.get(i).getKey();
            collegeList.add(itemCollegeName);

            countList.add(collegeGroupList.get(i).getValue().intValue());

            int itemReadCount = (int) pushInformationList.stream().filter(d -> PushInformationConstants.READ_STATE_READ == d.getReadState()
            && itemCollegeName.equals(d.getCollegeName())).count();
            readCountList.add(itemReadCount);
        }

        vo.setCollegeNames(collegeList.toArray(new String[0]));
        vo.setCollegeCounts(countList.stream().mapToInt(Integer::intValue).toArray());
        vo.setCollegeReadCounts(readCountList.stream().mapToInt(Integer::intValue).toArray());

        return JsonResult.ok().setData(vo);
    }

    @PreAuthorize("hasAuthority('big:data')")
    @ApiOperation(value = "单位")
    @GetMapping("/big/data/company")
    public JsonResult company() {
        BigDataCompanyVO vo = new BigDataCompanyVO();

        // 所有审核通过单位
        List<Company> companyList = companyService.list(new LambdaQueryWrapper<Company>().eq(Company::getState, CompanyConstants.COMPANY_STATE_PASS));

        // 单位所在市分组计数 倒叙排序
        Map<String, Long> cityGroupMap = companyList.stream().collect(Collectors.groupingBy(Company::getCity, Collectors.counting()));
        List<Map.Entry<String, Long>> cityGroupList = new ArrayList<Map.Entry<String, Long>>(cityGroupMap.entrySet());
        cityGroupList.sort(new Comparator<Map.Entry<String, Long>>() {
            public int compare(Map.Entry<String, Long> o1, Map.Entry<String, Long> o2) {
                return (int) (o2.getValue() - o1.getValue());
            }
        });

        // 单位行业分组计数 倒叙排序
        Map<String, Long> industryGroupMap = companyList.stream().collect(Collectors.groupingBy(Company::getIndustry, Collectors.counting()));
        List<Map.Entry<String, Long>> industryGroupList = new ArrayList<Map.Entry<String, Long>>(industryGroupMap.entrySet());
        industryGroupList.sort(new Comparator<Map.Entry<String, Long>>() {
            public int compare(Map.Entry<String, Long> o1, Map.Entry<String, Long> o2) {
                return (int) (o2.getValue() - o1.getValue());
            }
        });

        // 所有有效单位招聘职位
        List<Position> positionList = positionService.list(new LambdaQueryWrapper<Position>().eq(Position::getState, "0"));

        // 招聘职位分组计数 倒叙排序
        Map<String, Long> positionGroupMap = positionList.stream().collect(Collectors.groupingBy(Position::getName, Collectors.counting()));
        List<Map.Entry<String, Long>> positionGroupList = new ArrayList<Map.Entry<String, Long>>(positionGroupMap.entrySet());
        positionGroupList.sort(new Comparator<Map.Entry<String, Long>>() {
            public int compare(Map.Entry<String, Long> o1, Map.Entry<String, Long> o2) {
                return (int) (o2.getValue() - o1.getValue());
            }
        });

        // 单位城市分布排名前三结果
        List<BigDataVO> cityResultList = new ArrayList<>();
        // 单位行业分布排名前三结果
        List<BigDataVO> industryResultList = new ArrayList<>();
        // 单位招聘职位分布排名前三结果
        List<BigDataVO> positionResultList = new ArrayList<>();
        for (int i = 0; i < 3; i++) {
            if (cityGroupList.size() >= i) {
                cityResultList.add(new BigDataVO(cityGroupList.get(i).getKey(), cityGroupList.get(i).getValue().intValue()));
            }
            if (industryGroupList.size() >= i) {
                industryResultList.add(new BigDataVO(industryGroupList.get(i).getKey(), industryGroupList.get(i).getValue().intValue()));
            }
            if (positionGroupList.size() >= i) {
                positionResultList.add(new BigDataVO(positionGroupList.get(i).getKey(), positionGroupList.get(i).getValue().intValue()));
            }
        }

        // 翻译单位行业为文本
        if (!CollectionUtil.isEmpty(industryResultList)) {
            List<Dict> dictList = dictService.cacheList(DictConstants.COMPANY_INDUSTRY);

            industryResultList.forEach(item -> {
                Dict dict = dictList.stream().filter(d -> d.getValue().equals(item.getName())).findFirst().orElse(null);
                item.setName(dict != null ? dict.getLabel() : "");
            });
        }

        vo.setCityList(cityResultList);
        vo.setIndustryList(industryResultList);
        vo.setPositionList(positionResultList);

        return JsonResult.ok().setData(vo);
    }

    @PreAuthorize("hasAuthority('big:data')")
    @ApiOperation(value = "就业咨询")
    @GetMapping("/big/data/jyzx")
    public JsonResult jyzx(Integer year) {
        BigDataJyzxVO vo = new BigDataJyzxVO();

        // 参数年份的起始时间
        Date current = DateUtil.parseDate(year + "-01-01");
        String startDate = DateUtil.formatDate(DateUtil.beginOfYear(current));
        String endDate = DateUtil.formatDate(DateUtil.endOfYear(current));

        // 预约咨询类型
        String[] typeNames = new String[] {CounselTypeEnum.GTFD.getLabel(), CounselTypeEnum.KYZT.getLabel(), CounselTypeEnum.KGZT.getLabel(), CounselTypeEnum.TTFD.getLabel()};
        vo.setTypeNames(typeNames);

        // 月份
        String[] monthNames = new String[] {"1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"};
        int[] monthValues = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
        vo.setMonthNames(monthNames);

        List<int[]> data = new ArrayList<>();

        // 已应约的学生一整年预约咨询数据
        List<CounselStudent> list = counselStudentService.listBigData(startDate, endDate);
        if (CollectionUtil.isEmpty(list)) {
            for (int i = 0; i < typeNames.length; i++) {
                data.add(new int[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});
            }

            vo.setData(data);
            return JsonResult.ok().setData(vo);
        }

        List<Integer> datas1 = new ArrayList<>();
        List<Integer> datas2 = new ArrayList<>();
        List<Integer> datas3 = new ArrayList<>();
        List<Integer> datas4 = new ArrayList<>();
        for (int month : monthValues) {
            int data1 = 0;
            int data2 = 0;
            int data3 = 0;
            int data4 = 0;
            for (CounselStudent item : list) {
                if (month != DateUtil.month(item.getCounselDate()) + 1) {
                    continue;
                }
                if (CounselTypeEnum.GTFD.getValue().equals(item.getCounselType())) {
                    data1++;
                }
                if (CounselTypeEnum.KYZT.getValue().equals(item.getCounselType())) {
                    data2++;
                }
                if (CounselTypeEnum.KGZT.getValue().equals(item.getCounselType())) {
                    data3++;
                }
                if (CounselTypeEnum.TTFD.getValue().equals(item.getCounselType())) {
                    data4++;
                }
            }

            datas1.add(data1);
            datas2.add(data2);
            datas3.add(data3);
            datas4.add(data4);
        }


        data.add(datas1.stream().mapToInt(Integer::intValue).toArray());
        data.add(datas2.stream().mapToInt(Integer::intValue).toArray());
        data.add(datas3.stream().mapToInt(Integer::intValue).toArray());
        data.add(datas4.stream().mapToInt(Integer::intValue).toArray());
        vo.setData(data);

        return JsonResult.ok().setData(vo);
    }

    @PreAuthorize("hasAuthority('big:data')")
    @ApiOperation(value = "100件事")
    @GetMapping("/big/data/ybjs")
    public JsonResult ybjs(Integer year, Integer degree) {
        BigDataYbjsVO vo = new BigDataYbjsVO();

        int[] years = new int[] {year, year - 1, year - 2, year - 3};
        vo.setYears(years);

        List<Integer> countStudentList = new ArrayList<>();
        List<Integer> countPepsiList = new ArrayList<>();
        for (int y : years) {
            int countStudent = pepsiStudentService.countStudent(y, degree);
            countStudentList.add(countStudent);

            int countPepsi = pepsiStudentService.countPepsi(y, degree);
            countPepsiList.add(countPepsi);
        }

        List<int[]> data = new ArrayList<>();
        data.add(countStudentList.stream().mapToInt(Integer::intValue).toArray());
        data.add(countPepsiList.stream().mapToInt(Integer::intValue).toArray());
        vo.setData(data);

        return JsonResult.ok().setData(vo);
    }

    /**
     * 年度区间
     * 例2023-09-01 00:00:00 2024-08-31 23:59:59
     *
     * @param year 年份
     * @return 日期区间
     */
    private String[] dateRange(Integer year) {
        Integer nextYear = year + 1;
        return new String[]{year + "-09-01 00:00:00", nextYear + "-08-31 23:59:59"};
    }

    private List<BigDataVO> buildBigDataVO(String data) {
        if (StrUtil.isBlank(data)) {
            return new ArrayList<>();
        }

        String[] strings = data.split(",");
        List<BigDataVO> list = new ArrayList<>();
        for (String item : strings) {
            BigDataVO vo = list.stream().filter(d -> d.getName().equals(item)).findFirst().orElse(null);
            if (vo == null) {
                BigDataVO bigDataVO = new BigDataVO();
                bigDataVO.setName(item);
                bigDataVO.setValue(1);
                list.add(bigDataVO);
            } else {
                vo.setValue(vo.getValue() + 1);
            }
        }

        // 降序排序
        list.sort(new Comparator<BigDataVO>() {
            @Override
            public int compare(BigDataVO o1, BigDataVO o2) {
                return Integer.compare(o2.getValue(), o1.getValue());
            }
        });

        return list;
    }

    /**
     * 生源地区翻译为具体省
     *
     * @param area 生源地区文本
     * @return 省名称
     */
    private String buildArea(String area) {
        if (StrUtil.isBlank(area)) {
            return "";
        }
        for (String item : AREA) {
            if (area.contains(item)) {
                return item;
            }
        }
        return "";
    }

}
